/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!
  \file			ETSI_Root.cc
  \date			september 2011
  \author		TNick

  \brief		Contains the implementation for ETSI_Root class


  Copyright (c) 2011, Nicu Tofan
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
 * Neither the name of the copyright holder nor the
   names of its contributors may be used to endorse or promote products
   derived from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL NICU TOFAN BE LIABLE FOR ANY
 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

#include	<main.h>

#include	<QPainter>

#include	"ETSI_Root.h"
#include	<sheet/ETSheet.h>

/*  INCLUDES    ============================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */
DDHC_CONTENT(ETSI_Root)

/* ------------------------------------------------------------------------- */
ETSI_Root::ETSI_Root	( void )
	: ETSubItem()
{
	DDHC_CONSTRUCT;
	DDHC_SUBITEM_VARS;

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
ETSI_Root::~ETSI_Root	( void )
{
	DDHC_DESTRUCT
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			ETSI_Root::recompute		(bool b_full)
{

	/* the SIZE_DIRTY flag is meaningless for this kind of sub-item
because it does not have any graphics of it's own */

	ETSubItem * itr_i = first();

	if (b_full == false)
	{ /* only recompute if this element is "dirty" */

		if (isKidSizeDirty() == false)
		{
			return;
		}

		/* iterate in all sub-items that are hosted by this one */
		while (itr_i != NULL)
		{
			if (itr_i->requireRecompute())
			{
				itr_i->recompute(b_full);
			}
			itr_i = itr_i->next();
		}
	}
	else
	{ /* forced recompute */

		/* iterate in all sub-items that are hosted by this one */
		while (itr_i != NULL)
		{
			itr_i->recompute(b_full);
			itr_i = itr_i->next();
		}
	}


	/* the bounding boxes were updated; it's time to arrange items */
	qreal	crt_x = 0;
	qreal	crt_t = 0;
	qreal	crt_b = 0;
	itr_i = first();
	while (itr_i != NULL)
	{

		itr_i->setPosX(crt_x - itr_i->boundingBox().x());
		crt_t = crt_t < itr_i->boundingBox().top() ?
					crt_t :
					itr_i->boundingBox().top();
		crt_b = crt_b > itr_i->boundingBox().bottom() ?
					crt_b :
					itr_i->boundingBox().bottom();

		crt_x += itr_i->width();
		itr_i = itr_i->next();
	}

	bbox.setCoords(0, crt_t, crt_x, crt_b);

	/* reset the flags that request a recompute */
	resetSizeFlags();

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void            ETSI_Root::paint               (
		ETSheetView * vp, QPainter *  painter, QPointF pt_ref)
{
	PaintData	pd(vp, painter, pt_ref);
	prePaint(&pd);

	ETSubItem * itr_i = first();
	while (itr_i != NULL)
	{
		pt_ref.setX(pt_ref.x() - itr_i->boundingBox().x());
		itr_i->paint(vp, painter,pt_ref);
		pt_ref.setX(pt_ref.x() + itr_i->boundingBox().right());

		itr_i = itr_i->next();
	}

	postPaint(&pd);
}
/* ========================================================================= */

///* ------------------------------------------------------------------------- */
//void			ETSI_Root::navKey		(
//	ETSheetView *	vp, Qt::Key key )
//{
//	Q_UNUSED(vp);
//	Q_UNUSED(key);

//}
///* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			ETSI_Root::hitTest		(HtData * h_data)
{

	ETSubItem * itr_i = first();
	while (itr_i != NULL)
	{
		/* get the bounding box for the sub-item in it's own coordinate system */
		h_data->rct_cache = itr_i->boundingBox();
		/* transform that coordinates in this item's coordinate system */
		h_data->rct_cache.translate(itr_i->posX(), 0);
		/* now convert them to ETI_CplxTxt item coordinates */
		h_data->rct_cache.translate(h_data->ref_pt);

		if (h_data->rct_cache.contains(h_data->ck_pt))
		{
			/* we already have computed the bounding box for this item */
			h_data->rct_bbx = h_data->rct_cache;
			/* and we're a step away from the reference point in item coords */
			h_data->ref_pt.setX(h_data->ref_pt.x()+itr_i->posX());
			itr_i->hitTest(h_data);
			return;
		}
		itr_i = itr_i->next();
	}

	h_data->it_hitted = this;
	h_data->true_hit = true;
	/* h_data->rct_bbx already set by the caller */
	h_data->int_data = 0;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			ETSI_Root::ackRemoveKid	(ETSubItem * kid)
{
	it_lst.remove(kid);

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
QPointF			ETSI_Root::subIRefPt	(const ETSubItem * p_kid) const
{
	return QPointF(p_kid->posX(), 0);
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
ETSI_Root *		ETSI_Root::loadXML		(
		QDomElement dom_e, ETSI_Root * existing)
{

	QDomElement dom_it;

#ifdef	APP_DEBUG
	/* type is assumed to be root */

	dom_it = dom_e.firstChildElement(XML_TAG_TYPE);
	if (!dom_it.isNull())
	{
		Q_ASSERT_X(dom_it.text() == XML_SIT_ROOT, __FUNCTION__,
				   QString("ETSI_Root::loadXML got an element of type <"
						   "%1> while expected type is " XML_SIT_ROOT)
				   .arg(dom_it.text()).toLatin1()
				   );
	}
#endif

	if (existing == NULL)
	{
		existing = new ETSI_Root();
	}

	/* the one and only common data to all kinds of sub-items */
	dom_it = dom_e.firstChildElement(XML_TAG_COMM);
	if (!dom_it.isNull())
	{
		ETSubItem::loadXMLCmn(existing, dom_it);

		if (!dom_it.nextSiblingElement(XML_TAG_COMM).isNull())
		{
			qDebug() << "The input presented more than one "
					 << "common tags, when only one per sub-item element "
					 << "is allowed";
		}
	}



	/* list of sub-items hosted by this root sub-item */
	dom_it = dom_e.firstChildElement(XML_TAG_SUBITEM);
	while (!dom_it.isNull())
	{
		ETSubItem * new_si = ETSubItem::loadXMLByType(dom_it);
		existing->append(new_si);
		dom_it = dom_it.nextSiblingElement(XML_TAG_SUBITEM);
	}

	return existing;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void		ETSI_Root::saveXML		(
		QDomElement dom_e)
{
	/* save the type */
	QDomElement dom_it = dom_e.ownerDocument().createElement(XML_TAG_TYPE);
	dom_e.appendChild(dom_it);
	QDomText dom_tx = dom_e.ownerDocument().createTextNode(XML_SIT_ROOT);
	dom_it.appendChild(dom_tx);


	/* save common properties */
	dom_it = dom_e.ownerDocument().createElement(XML_TAG_COMM);
	dom_e.appendChild(dom_it);
	saveXMLCmn(dom_it);


	/* now specifics */
	ETSubItem * itr_i = first();
	while (itr_i != NULL)
	{
		dom_it = dom_e.ownerDocument()
				.createElement(XML_TAG_SUBITEM);
		dom_e.appendChild(dom_it);
		itr_i->saveXML(dom_it);
		itr_i = itr_i->next();
	}

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool		ETSI_Root::loadEbdXmlRootSi		(
		ETSI_Root * out_rt, QDomElement dom_e )
{
	QDomElement		dom_sit;
	QDomElement		dom_it;
	QDomElement		dom_it2;

	/* the one and only sub-item that has to be of root type */
	dom_it = dom_e.firstChildElement(XML_TAG_SUBITEM);
	if (!dom_it.isNull())
	{
		dom_sit = dom_it.firstChildElement(XML_TAG_TYPE);
		if (!dom_sit.isNull())
		{ /* silently ignore the lack of type and assume root */

			if (dom_sit.text() != XML_SIT_ROOT)
			{

				qDebug() << "The input presented an sub-item that "
						 << "was not of root type. The only "
						 << "sub-item in a numerator needs to be "
						 << "of root type. Period.";
				return false;

			}
		}

		/* this call will load entire chain of sub-items */
		ETSI_Root::loadXML(dom_it2, out_rt);

		if (!dom_it2.nextSiblingElement(XML_TAG_SUBITEM).isNull())
		{
			qDebug() << "The input presented to ETSI_Fract::loadXML more than one "
					 << XML_TAG_SUBITEM << " tags, when only one per sub-item element "
					 << "is allowed";
		}
	}

	return true;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool		ETSI_Root::loadEbdXmlRoot		(
		QString node_name, ETSI_Root * out_rt, QDomElement dom_e )
{
	QDomElement		dom_it;

	dom_it = dom_e.firstChildElement(node_name);
	if (!dom_it.isNull())
	{

		if (!loadEbdXmlRootSi(out_rt, dom_it))
		{
			return false;
		}

		if (!dom_it.nextSiblingElement(node_name).isNull())
		{
			qDebug() << "The input presented to ETSI_Fract::loadXML more than one "
					 << node_name << " tags, when only one per sub-item element "
					 << "is allowed";
		}
	}

	return true;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool				ETSI_Root::hitEmbAid		(HtData * h_data, qreal dx, qreal dy)
{
	/* get the bounding box for the sub-item in it's own coordinate system */
	h_data->rct_cache = boundingBox();
	/* transform that coordinates in this sub-item's coordinate system */
	h_data->rct_cache.translate(dx, dy);
	/* now convert them to ETI_CplxTxt item coordinates */
	h_data->rct_cache.translate(h_data->ref_pt);

	if (h_data->rct_cache.contains(h_data->ck_pt))
	{
		/* we already have computed the bounding box for this item */
		h_data->rct_bbx = h_data->rct_cache;
		/* and we're a step away from the reference point in item coords */
		h_data->ref_pt.setX(h_data->ref_pt.x() + dx);
		h_data->ref_pt.setY(h_data->ref_pt.y() + dy);
		hitTest(h_data);
		return true;
	}

	return false;
}
/* ========================================================================= */

/*  CLASS    =============================================================== */
//
//
//
//
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
